
//
//  PViewController.swift
//  jotravel
//
//  Created by tong on 16/2/25.
//  Copyright © 2016年 qicaibuluo. All rights reserved.
//

import Eelay



public struct PageConfig{
    public static var page_size_key = "pagemax"
    public static var page_key = "page"
    public static var default_page_size = 10
    public static var page_begin = 1
    public static var node:String? = nil
    public static var is_index_page_key = false //该值为true时是请求 第n条以后的10条 ，为false时是请求第n页以后的10条
    
    
    //数据请求成功，请求失败， 数据为空的判断逻辑
    public static var dataStatusJudge:(RootData?,JoPage) ->PageDataStatus = { respense,page in
        var node = ""
        let nodes = (page.node ?? "XX").components(separatedBy: ".")
        if nodes.count > 0
        {
            node = nodes.first ?? node
        }
        
        if let obj = respense as? NSMutableDictionary
        {
            guard let list = DataNode<NSMutableArray>.path(node: page.node ?? "", obj) else{
                return .err("未获取到[XX]数据列表".replaceVars(values: "\(node)"))
            }
            
            if page.page <= (page.page_begin){
                if list.count < 1
                {
                    return .empty(page.empty_msg)
                }
            }
            if list.count < page.page_size
            {
                
                return .loadFinished("数据加载完成".loc,list)
            }
            else{
                return .normal("数据加载成功".loc,list)
            }
        }
        if let list = respense as? NSMutableArray{
            if node == ""
            {
                
                if page.page <= (page.page_begin){
                    if list.count < 1
                    {
                        return .empty(page.empty_msg)
                    }
                }
                if list.count < page.page_size
                {
                    return .loadFinished("数据加载完成".loc,list)
                }
                else{
                    return .normal("数据加载成功".loc,list)
                }
            }
        }
        return .err("未获取到有效的数据对象".loc)
    }
}


private let test_request = true



public enum RefreshJust{
    case normal
    case safe
}


public enum PageDataStatus {
    case err(String)
    case loadFinished(String,NSMutableArray)
    case empty(String)
    case normal(String,NSMutableArray)
    
    public var datas:NSMutableArray?{
        get{
            switch self {
            case .err(_):
                return nil
            case .normal(_, let list):
                return list
            case .loadFinished(_, let list):
                return list
            case .empty:
                return NSMutableArray()
            }
        }
    }
    
    public var message:String{
        switch self {
        case .err(let message),.loadFinished(let message, _),.normal(let message,_),.empty(let message):
            return message
        }
    }
}



public class JoPage:NSObject
{
    public enum Trigger {
        case header
        case footer
        case unkown
        case none
    }
    
    public var recentTrigger:Trigger = .none
    
    public var type:JoPageType = .full
    public var net = JoTask(){
        didSet{
            switch net.apimode {
            case .apijson(_):
                self.page_begin = 0
            default:
                break
            }
        }
    }
    
    public var in_test = false{
        didSet{
            if !in_test{
                
            }
        }
    }
    
    public var refreshHeader:MoPageHeader? = MoRefreshHead()
    public var moreFooter:MoPageFooter? = MJRefreshFoot()
    
    
    
    public var one_obj_model = false
    
    public var empty_msg = "没有相关内容"
    
    public var node:String? = PageConfig.node
    public var page = PageConfig.page_begin
    public var page_size = PageConfig.default_page_size{
        didSet{
            last_page_count = page_size
        }
    }
    public var last_page_count = PageConfig.default_page_size
    public var is_index_page_key = PageConfig.is_index_page_key
    public var page_begin = PageConfig.page_begin
    
    public var page_key = PageConfig.page_key
    public var page_size_key = PageConfig.page_size_key

    
    public var statusJudge:(RootData?,JoPage) ->PageDataStatus = PageConfig.dataStatusJudge
    
    public var parameters:[String:Any] = [:]
    
    public func get_params()->[String:Any]
    {
        switch net.apimode {
        case .apijson(_):
            self.page_begin = 0
        default:
            break
        }
        
        var page_info = [page_key:self.page,page_size_key:self.page_size]
        
        if self.is_index_page_key{
            page_info[page_key] = self.page * self.page_size
        }
        
        if self.one_obj_model
        {
            page_info.removeAll()
        }
        
        switch net.apimode {
        case .apijson(let apijson):
            var task = ApijsonTask(request: apijson, response: nil)
            
            let params = task.appendPageParams(paginator: self,page: page, count: page_size)
            //            let params = page_info + self.parameters
            return params
        default:
            let params = page_info + self.parameters
            return params
        }
    }
    
    public var item_creater : () -> AnyObject = {() in return SandBox.one()}
    
    
    deinit{
        
    }
}





extension NSObject
{
    private struct __extention_keys {
        static var base = "__extention"
    }
    
    public var __extention: NSMutableDictionary {
        get {
            
            if let obj = objc_getAssociatedObject(self, &__extention_keys.base) as? NSMutableDictionary
            {
                return obj
            }
            else
            {
                let dict = NSMutableDictionary()
                objc_setAssociatedObject(self, &__extention_keys.base, dict, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
                return dict
            }
        }
    }
    
}

public enum JoPageType:Int
{
    case full = 0
    case top = 1
    case bottom = 2
    case none = -1
}



public protocol Paginator:NSObjectProtocol{
    
    var pagingScrollView:UIScrollView {get set}
    
    var paginator:JoPage{get set}
    
    var backMsgView:UIView{get set}
    
    func load(page: Int, succeed: Bool, list: [Any], response: RootData?, status: PageDataStatus, scrollView: UIScrollView)
    
    func pageRequest()
    
    func refresh()
    
}

extension TypeInitController{
    @objc func dofs(){
        
    }
}

extension Paginator where Self:NSObject
{
    
    
    public var backMsgView:UIView{
        get{
            if let  v = __extention.object(forKey: "backMsgView") as? UIView
            {
                return v
            }
            let v = UILabel()
            v.backgroundColor = .clear
            //            v.textAlignment = .center
            _ = v.ui.center.text(color: .color(light: "#999", dark: "#ccc9")).font16
            __extention.setObject(v, forKey: "backMsgView" as NSCopying)
            return v
        }
        set{
            __extention.setObject(newValue, forKey: "backMsgView" as NSCopying)
        }
    }
    
    public var pagingScrollView:UIScrollView
    {
        set{
            __extention.setObject(newValue, forKey: "scrollView" as NSCopying)
        }
        
        get{
            if let  v = __extention.object(forKey: "scrollView") as? UIScrollView
            {
                return v
            }
            return UIScrollView()
        }
    }
    
    public var paginator:JoPage{
        
        get{
            if let p = __extention.object(forKey: "paginator") as? JoPage
            {
                return p
            }
            else
            {
                let p = JoPage()
                __extention.setObject(p, forKey: "paginator" as NSCopying)
                return p
            }
        }
        
        set{
            __extention.setObject(newValue, forKey: "paginator" as NSCopying)
        }
    }
    
    
    
    public func addPaginatorViews()
    {
        
     
        
        self.__extention.setObject("YES", forKey: "loaded" as NSCopying)
//        weak var wself = self
        
        if let tableV = self.pagingScrollView as? UICollectionView
        {
            
            if let msgL = backMsgView as? UILabel{
                _ = msgL.ui.text(color: .color(light: "#999", dark: "#ccc9")).font16.center
            }
            tableV.backgroundView = self.backMsgView
            
            //            collectionV.ableRefreshAndLoadMore(self.paginator.type.rawValue)
            
            
            switch self.paginator.type {
            case .full:
                addRefreshHeader()
                addRefreshFooter()
            case .top:
                addRefreshHeader()
            case .bottom:
                addRefreshFooter()
            case .none:
                break
            }
            return
            
        }
        
        if let tableV = self.pagingScrollView as? UITableView
        {
            
            
            tableV.backgroundView = self.backMsgView
            
            _ = self.paginator.type
            switch self.paginator.type {
            case .full:
                addRefreshHeader()
                addRefreshFooter()
            case .top:
                addRefreshHeader()
            case .bottom:
                addRefreshFooter()
            case .none:
                break
            }
            return
            
            
        }
      
            
            
        _ = self.paginator.type
        switch self.paginator.type {
        case .full:
            addRefreshHeader()
            addRefreshFooter()
        case .top:
            addRefreshHeader()
        case .bottom:
            addRefreshFooter()
        case .none:
            break
        }
        
            
        
        
    }
    
    
    func addRefreshFooter() {
        switch paginator.net.apimode {
        case .apijson(_):
            paginator.page_begin = 0
        default:
            break
        }
        paginator.moreFooter?.loadBlock = {[weak self] in
//            print("-----------------uuuiiii|loadBlock")
            self?.paginator.recentTrigger = .footer
            self?.pageRequest()
        }
        paginator.moreFooter?.setScrollView(scrollView: pagingScrollView)
        
    }
    
    func addRefreshHeader() {
        
        
        switch paginator.net.apimode {
        case .apijson(_):
            paginator.page_begin = 0
        default:
            break
        }
        self.paginator.refreshHeader?.setScrollView(scrollView: pagingScrollView)
        paginator.refreshHeader?.refreshBlock = {[weak self] in
            guard self != nil else {
                return
            }
            self?.paginator.recentTrigger = .header
            self?.paginator.page = (self?.paginator.page_begin ?? PageConfig.page_begin) - 1
            self?.pageRequest()
        }
    }
  
   
    
    
}

extension Paginator where Self:NSObject
{
    
    
    public func load(page: Int, succeed: Bool, list: [Any], response: RootData?, status: PageDataStatus, scrollView: UIScrollView) {
        
        if let leb = self.backMsgView as? UILabel
        {
            leb.text = ""
        }
        
        
        if let tb_view = scrollView as? UITableView
        {
            
            if succeed
            {
                
                if let items = tb_view.model[obj:"section0",nil] as? NSMutableArray
                {
                    
                    if page == self.paginator.page_begin
                    {
                        items.removeAllObjects()
                    }
                    items.addObjects(from: list)
                    if items.count < 1
                    {
                        if let leb = self.backMsgView as? UILabel
                        {
                            leb.text = self.paginator.empty_msg
                        }
                    }
                    else
                    {
                    }
                    tb_view.reloadData()
                }
            }
            
        }
        
    }
    
}


extension Paginator where Self:NSObject
{
    
    
    private var page_handle:JoResponse.json_response
    {
        get{
            weak var wself = self
            let block:JoResponse.json_response = { (status, message, obj, response) -> Void in
                
                if let ws = wself
                {                    
                    if status.isSuccess{
                    
                        if ws.paginator.one_obj_model
                        {
                            if let dict  = obj as? NSMutableDictionary
                            {
                                
                                let node = wself?.paginator.node ?? "list"
                                ws.pageData(response: ["\(node)":[dict].mutable_array])
                                return
                            }
                        }
                        else
                        {
                            if let dict = obj as? NSMutableDictionary
                            {
                                ws.pageData(response: dict)
                                return
                            }
                            if let list = obj as? NSMutableArray
                            {
                                ws.pageData(response: list)
                                return
                            }
                            
                        }
                    }
                    wself?.paginagtorFailedRequest()
                }
            }
            return block
        }
    }
    
    
    public func pageRequest()
    {
        self.paginator.page = self.paginator.page + 1
        
        if paginator.page == PageConfig.page_begin
        {
            //            self.pagingScrollView.mj_footer?.endRefreshingWithNoMoreData()
        }
        if self.paginator.in_test
        {
            self.testPageRequest()
            
        }
        else
        {
            self.netPageRequest()
        }
        
    }
    
    func netPageRequest(){
        let p = self.paginator.get_params()
        self.paginator.net.params(p).json_handle(self.page_handle).run()
    }
    
    func testPageRequest()
    {
        let request = JoClient()
        weak var wself = self
        request.requestPageData(page: 0, size: self.paginator.page_size, itemCreator: self.paginator.item_creater, sucess: { (list:[AnyObject]) -> Void in
            if let ws = wself
            {
                let node = self.paginator.node ?? "list"
                ws.pageData(response: ["\(node)":list.mutable_array].mutable_dictionary)
            }
        })
    }
    
    
    
    
    public func pageData(response:RootData?)
    {
        let page = self.paginator.page
        
        let paginator = self.paginator
        let status = self.paginator.statusJudge(response, paginator)
        
        let datas = status.datas ?? NSMutableArray()
        
        
        
        var end = false
        switch status {
        case .loadFinished,.err,.empty:
            end = true
        default:
            break
        }
        //        let end = (datas.count < self.paginator.page_size) ? true:false
        
        
        self.paginator.last_page_count = datas.count
        if self.paginator.page == paginator.page_begin
        {
            switch self.paginator.type {
            case .top,.full:
                paginator.refreshHeader?.endRefreshing()
            default:
                break
            }
            
            switch self.paginator.type {
            case .bottom,.full:
                paginator.moreFooter?.resetNoMoreData()
            default:
                break
            }
        }
        else
        {
            
            paginator.moreFooter?.endLoad()
        }
        if end
        {
            switch self.paginator.type {
            case .bottom,.full:
                paginator.moreFooter?.endLoadWithNoMoreData()
            default:
                break
            }
            
        }
                
        load(page:page, succeed: true, list: datas as! [Any], response: response, status: status, scrollView: self.pagingScrollView)
        
    }
    
  
    
    func paginagtorFailedRequest()
    {
        if self.paginator.page == paginator.page_begin
        {
            paginator.refreshHeader?.endRefreshing()
            paginator.moreFooter?.endLoad()
            switch self.paginator.type {
            case .bottom,.full:
                paginator.moreFooter?.resetNoMoreData()
            default:
                break
            }
        }
        else
        {
            paginator.refreshHeader?.endRefreshing()
            paginator.moreFooter?.endLoad()
            switch self.paginator.type {
            case .bottom,.full:
                paginator.moreFooter?.endLoadWithNoMoreData()
            default:
                break
            }
            
        }
        
        load(page:  self.paginator.page, succeed: false, list: [Any](), response: nil, status: .err("数据请求失败"), scrollView: self.pagingScrollView)
        self.paginator.page = self.paginator.page - 1
        if paginator.page < self.paginator.page_begin
        {
            paginator.page = self.paginator.page_begin
        }
        
    }
    
    

    public func refresh()
    {
        
        var load = "NO"
        
        if let have_load = __extention.object(forKey: "loaded") as? String
        {
            load  = have_load
        }
        if load == "NO"
        {
            self.addPaginatorViews()
        }
        
        if self.pagingScrollView is UITableView
        {
            paginator.refreshHeader?.beginRefresh()
            //            tableV.performSelector(#selector(UITableView.refreshHeader), withObject: nil, afterDelay: 0.1)
        }
        
        if self.pagingScrollView is UICollectionView
        {
            paginator.refreshHeader?.beginRefresh()

            //            tableV.performSelector(#selector(UICollectionView.refreshHeader), withObject: nil, afterDelay: 0.1)
        }
        
    }
    
    public func loadMore(page:Int,justNow:Bool=true)
    {
        
        var _just_now = justNow
        paginator.page = page - 1
        var load = "NO"
        if let have_load = __extention.object(forKey: "loaded") as? String
        {
            load  = have_load
        }
        if load == "NO"
        {
            self.addPaginatorViews()
        }
        if paginator.in_test{
            _just_now = true
        }
        if _just_now
        {
            paginator.recentTrigger = .unkown
            pageRequest()
        }
        else{
            if self.pagingScrollView is UITableView
            {
                paginator.moreFooter?.beginLoad()
//                tableV.mj_footer?.beginRefreshing()
            }
            
            if self.pagingScrollView is UICollectionView
            {
                paginator.moreFooter?.beginLoad()
                
//                tableV.mj_footer?.beginRefreshing()
            }
        }
    }
    
}




